home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / comm / wnos5src.zip / TCPSUBR.C < prev    next >
Text File  |  1993-08-09  |  6KB  |  292 lines

  1. /* Low level TCP routines:
  2.  *  control block management
  3.  *  sequence number logical operations
  4.  *  state transitions
  5.  *  RTT cacheing
  6.  *
  7.  * Copyright 1991 Phil Karn, KA9Q
  8.  */
  9. #include <stdio.h>
  10. #include "global.h"
  11. #include "timer.h"
  12. #include "mbuf.h"
  13. #include "netuser.h"
  14. #include "internet.h"
  15. #include "tcp.h"
  16. #include "ip.h"
  17.  
  18. /* TCP connection states */
  19. char *Tcpstates[] = {
  20.     "",
  21.     "Closed",
  22.     "Listen",
  23.     "SYN sent",
  24.     "SYN rcvd",
  25.     "Established",
  26.     "FIN wait 1",
  27.     "FIN wait 2",
  28.     "Close wait",
  29.     "Last ACK",
  30.     "Closing",
  31.     "Time wait"
  32. };
  33.  
  34. /* TCP closing reasons */
  35. char *Tcpreasons[] = {
  36.     "Normal",
  37.     "Reset/Refused",
  38.     "Timeout",
  39.     "ICMP"
  40. };
  41.  
  42. int16 Tcp_mss = DEF_MSS;    /* Maximum segment size to be sent with SYN */
  43. int32 Tcp_irtt = DEF_RTT;    /* Initial guess at round trip time */
  44. int Tcp_trace = FALSE;        /* State change tracing flag */
  45. int Tcp_syndata = FALSE;
  46. struct tcp_rtt Tcp_rtt[RTTCACHE];
  47. struct tcb *Tcbs = NULLTCB;
  48.  
  49. struct mib_entry Tcp_mib[] = {
  50.     NULLCHAR,        0,
  51.     "RtoAlgorithm",    4,            /* Van Jacobsen's algorithm */
  52.     "RtoMin",        0,            /* No lower bound */
  53.     "RtoMax",        MAXINT32,    /* No upper bound */
  54.     "MaxConn",        -1L,        /* No limit */
  55.     "ActiveOpens",    0,
  56.     "PassiveOpens",    0,
  57.     "AttemptFails",    0,
  58.     "EstabResets",    0,
  59.     "CurrEstab",    0,
  60.     "InSegs",        0,
  61.     "OutSegs",        0,
  62.     "RetransSegs",    0,
  63.     NULLCHAR,        0,            /* Connection state goes here */
  64.     "InErrs",        0,
  65.     "OutRsts",        0,
  66. };
  67.  
  68. /* Look up TCP connection
  69.  * Return TCB pointer or NULLTCB if nonexistant.
  70.  * Also move the entry to the top of the list to speed future searches.
  71.  */
  72. struct tcb *
  73. lookup_tcb(struct connection *conn)
  74. {
  75.     struct tcb *tcb, *tcblast = NULLTCB;
  76.  
  77.     for(tcb = Tcbs; tcb != NULLTCB; tcblast = tcb, tcb = tcb->next) {
  78.         /* Yet another structure compatibility hack */
  79.         if(conn->remote.port == tcb->conn.remote.port
  80.          && conn->local.port == tcb->conn.local.port
  81.          && conn->remote.address == tcb->conn.remote.address
  82.          && conn->local.address == tcb->conn.local.address) {
  83.             if(tcblast != NULLTCB) {
  84.                 /* Move to top of list */
  85.                 tcblast->next = tcb->next;
  86.                 tcb->next = Tcbs;
  87.                 Tcbs = tcb;
  88.             }
  89.             return tcb;
  90.         }
  91.     }
  92.     return NULLTCB;
  93. }
  94.  
  95. /* Create a TCB, return pointer. Return pointer if TCB already exists. */
  96. struct tcb *
  97. create_tcb(struct connection *conn)
  98. {
  99.     struct tcb *tcb;
  100.  
  101.     if((tcb = lookup_tcb(conn)) == NULLTCB) {
  102.         struct tcp_rtt *tp;
  103.  
  104.         tcb = mxallocw(sizeof(struct tcb));
  105.         ASSIGN(tcb->conn,*conn);
  106.  
  107.         tcb->state = TCP_CLOSED;
  108.         tcb->cwind = tcb->mss = Tcp_mss;
  109.         tcb->ssthresh = 65535L;
  110.  
  111.         if((tp = rtt_get(tcb->conn.remote.address)) != NULLRTT) {
  112.             tcb->srtt = tp->srtt;
  113.             tcb->mdev = tp->mdev;
  114.         } else {
  115.             tcb->srtt = Tcp_irtt;                /* mdev = 0 */
  116.         }
  117.         /* Initialize timer intervals */
  118.         tcb->timer.func = tcp_timeout;
  119.         tcb->timer.arg = tcb;
  120.         set_timer(&tcb->timer,tcb->srtt);
  121.  
  122.         tcb->next = Tcbs;
  123.         Tcbs = tcb;
  124.     }
  125.     return tcb;
  126. }
  127.  
  128. /* Close our TCB */
  129. void
  130. close_self(struct tcb *tcb,int reason)
  131. {
  132.     if(tcb != NULLTCB) {
  133.         struct reseq *res, *restmp = NULLRESEQ;
  134.  
  135.         stop_timer(&tcb->timer);
  136.  
  137.         /* Flush reassembly queue; nothing more can arrive */
  138.         for(res = tcb->reseq; res != NULLRESEQ; res = restmp) {
  139.             restmp = res->next;
  140.             free_p(res->bp);
  141.             xfree(res);
  142.         }
  143.         tcb->reseq = NULLRESEQ;
  144.         tcb->reason = reason;
  145.         setstate(tcb,TCP_CLOSED);
  146.     }
  147. }
  148.  
  149. /* Sequence number comparisons
  150.  * Return true if x is between low and high inclusive,
  151.  * false otherwise
  152.  */
  153. int
  154. seq_within(int32 x,int32 low,int32 high)
  155. {
  156.     if(low <= high) {
  157.         if(low <= x && x <= high) {
  158.             return 1;
  159.         }
  160.     } else {
  161.         if(low >= x && x >= high) {
  162.             return 1;
  163.         }
  164.     }
  165.     return 0;
  166. }
  167.  
  168. int
  169. seq_lt(int32 x,int32 y)
  170. {
  171.     return (long)(x-y) < 0;
  172. }
  173.  
  174. #ifdef XXX
  175. int
  176. seq_le(int32 x,int32 y)
  177. {
  178.     return (int)(x-y) <= 0;
  179. }
  180. #endif
  181.  
  182. int
  183. seq_gt(int32 x,int32 y)
  184. {
  185.     return (long)(x-y) > 0;
  186. }
  187.  
  188. int
  189. seq_ge(int32 x,int32 y)
  190. {
  191.     return (long)(x-y) >= 0;
  192. }
  193.  
  194. void
  195. setstate(struct tcb *tcb,int newstate)
  196. {
  197.     int oldstate = tcb->state;
  198.  
  199.     tcb->state = newstate;
  200.  
  201.     if(Tcp_trace && !uploadstatus)
  202.         tprintf("TCB %lx %s -> %s\n",ptol(tcb),
  203.             Tcpstates[oldstate],Tcpstates[newstate]);
  204.  
  205.     /* Update MIB variables */
  206.     switch(oldstate){
  207.     case TCP_CLOSED:
  208.         if(newstate == TCP_SYN_SENT)
  209.             tcpActiveOpens++;
  210.         break;
  211.     case TCP_LISTEN:
  212.         if(newstate == TCP_SYN_RECEIVED)
  213.             tcpPassiveOpens++;
  214.         break;
  215.     case TCP_SYN_SENT:
  216.         if(newstate == TCP_CLOSED)
  217.             tcpAttemptFails++;
  218.         break;
  219.     case TCP_SYN_RECEIVED:
  220.         switch(newstate){
  221.         case TCP_CLOSED:
  222.         case TCP_LISTEN:
  223.             tcpAttemptFails++;
  224.             break;
  225.         }
  226.         break;
  227.     case TCP_ESTABLISHED:
  228.     case TCP_CLOSE_WAIT:
  229.         switch(newstate){
  230.         case TCP_CLOSED:
  231.         case TCP_LISTEN:
  232.             tcpEstabResets++;
  233.             break;
  234.         }
  235.         tcpCurrEstab--;
  236.         break;
  237.     }
  238.     if(newstate == TCP_ESTABLISHED || newstate == TCP_CLOSE_WAIT)
  239.         tcpCurrEstab++;
  240.  
  241.     if(tcb->s_upcall)
  242.         (*tcb->s_upcall)(tcb,oldstate,newstate);
  243.  
  244.     switch(newstate){
  245.     case TCP_SYN_RECEIVED:
  246.     case TCP_ESTABLISHED:
  247.         /* Notify the user that he can begin sending data */
  248.         if(tcb->t_upcall)
  249.             (*tcb->t_upcall)(tcb,tcb->window - tcb->sndcnt);
  250.         break;
  251.     }
  252. }
  253.  
  254. /* Round trip timing cache routines.
  255.  * These functions implement a very simple system for keeping track of
  256.  * network performance for future use in new connections.
  257.  * The emphasis here is on speed of update (rather than optimum cache hit
  258.  * ratio) since rtt_add is called every time a TCP connection updates
  259.  * its round trip estimate.
  260.  */
  261. void
  262. rtt_add(int32 addr,int32 rtt)
  263. {
  264.     if(addr != 0) {
  265.         struct tcp_rtt *tp = &Tcp_rtt[(unsigned short)addr % RTTCACHE];
  266.  
  267.         if(tp->addr != addr) {
  268.             /* New entry */
  269.             tp->addr = addr;
  270.             tp->srtt = rtt;
  271.             tp->mdev = 0;
  272.         } else {
  273.             /* Run our own SRTT and MDEV integrators, with rounding */
  274.             int32 abserr = (rtt > tp->srtt) ? rtt - tp->srtt : tp->srtt - rtt;
  275.             tp->srtt = ((AGAIN-1) * tp->srtt + rtt + (AGAIN/2)) >> LAGAIN;
  276.             tp->mdev = ((DGAIN-1) * tp->mdev + abserr + (DGAIN/2)) >> LDGAIN;
  277.         }
  278.     }
  279. }
  280.  
  281. struct tcp_rtt *
  282. rtt_get(int32 addr)
  283. {
  284.     struct tcp_rtt *tp = &Tcp_rtt[(unsigned short)addr % RTTCACHE];
  285.  
  286.     if(addr == 0 || tp->addr != addr)
  287.         return NULLRTT;
  288.  
  289.     return tp;
  290. }
  291.  
  292.